/*
* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. 
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef PLUGIN_MANAGER_H
#define PLUGIN_MANAGER_H

#include <map>
#include <memory>
#include <mutex>

#include "ai_interpreter.h"
#include "plugin_manager/include/plugin_manager.h"
#include "plugin_manager/include/plugin.h"
#include "utils/infer_macros.h"

namespace OHOS {
namespace AI_STD {
//class AIInterpreter;

struct PluginKey {
    std::string aid;
    long long version;
    int frwk;

    PluginKey(const std::string &aid, long long version, int frwk)
        : aid(aid), version(version), frwk(frwk)
    {
    }

    inline bool operator< (const PluginKey& another) const
    {
        if (aid < another.aid) {
            return true;
        }

        if (frwk < another.frwk) {
            return true;
        }

        if (aid == another.aid && version < another.version) {
            return true;
        }

        return false;
    }
};

typedef std::map<PluginKey, std::shared_ptr<Plugin>> PluginMap;

class PluginManager {
    FORBID_COPY_AND_ASSIGN(PluginManager);
    FORBID_CREATE_BY_SELF(PluginManager);
public:
    /**
     * Create plugin manager.
     *
     * @return plugin manager
     */
    static PluginManager *GetInstance();
    /**
     * Destroy plugin.
     */
    void Destroy();
    /**
     * Get plugin.
     *
     * @param [in] aid Algorithm id
     * @param [in] version Algorithm version
     * @param [out] plugin Plugin
     * @return Returns RETCODE_SUCCESS(0) if the operation is successful, returns a non-zero value otherwise.
     */
    int GetPlugin(const AlgorithmInfo &algoInfo, std::shared_ptr<Plugin> &plugin);
    /**
     * Unload plugin.
     *
     * @param [in] aid Algorithm id
     * @param [in] version Algorithm version
     */
    void UnloadPlugin(const std::string &aid, long long version, int frwk);

private:
    std::shared_ptr<Plugin> FindPlugin(const PluginKey &pluginKey);
    void AddPlugin(const PluginKey &pluginKey, const std::shared_ptr<Plugin> &pluginValue);
    void DelPlugin(const PluginKey &pluginKey);
    void DelPluginByAID(const std::string &aid);
    int LoadPlugin(const AlgorithmInfo &algoInfo, std::shared_ptr<Plugin> &plugin);

private:
    static std::mutex instanceLock_;
    static PluginManager *instance_;

private:
    std::mutex mutex4Interface_;
    std::mutex mutex_;
    PluginMap pluginMap_;
};
} // namespace AI_STD
} // namespace OHOS

#endif // PLUGIN_MANAGER_H
